---
title: "Spring Async"
date: 2020-3-1
categories:
- java
- spring
tags:
---

<div id="content">
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#org39f6ecd">Get Start with @Async Annotation</a>
<ul>
<li><a href="#org5bbdac5">Enable Asnyc</a>
<ul>
<li><a href="#org0eda4f4">方法级别的设置</a></li>
<li><a href="#org74b5c87">应用级别的设置</a></li>
</ul>
</li>
<li><a href="#org1b46606">方法上的 @Async 注解</a>
<ul>
<li><a href="#orga6b0a95">void</a></li>
<li><a href="#org1112362">有返回值的异步方法</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<blockquote>
<p>
<a href="https://www.baeldung.com/spring-async">https://www.baeldung.com/spring-async</a>
</p>
</blockquote>
<div class="outline-2" id="outline-container-org39f6ecd">
<h2 id="org39f6ecd">Get Start with @Async Annotation</h2>
<div class="outline-text-2" id="text-org39f6ecd">
</div>
<div class="outline-3" id="outline-container-org5bbdac5">
<h3 id="org5bbdac5">Enable Asnyc</h3>
<div class="outline-text-3" id="text-org5bbdac5">
<div class="org-src-container">
<pre class="src src-java"><span style="font-weight: bold; text-decoration: underline;">@Configuration</span>
<span style="font-weight: bold; text-decoration: underline;">@EnableAsync</span>
<span style="font-weight: bold;">public</span> <span style="font-weight: bold;">class</span> <span style="font-weight: bold; text-decoration: underline;">AsyncConfig</span> {

  <span style="font-weight: bold; text-decoration: underline;">@Bean</span>
  <span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">Executor</span> <span style="font-weight: bold;">taskExecutor</span>() {
    <span style="font-weight: bold; text-decoration: underline;">ThreadPoolTaskExecutor</span> <span style="font-weight: bold; font-style: italic;">executor</span> = <span style="font-weight: bold;">new</span> <span style="font-weight: bold; text-decoration: underline;">ThreadPoolTaskExecutor</span>();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(20);
    executor.setQueueCapacity(500);
    executor.setThreadNamePrefix(<span style="font-style: italic;">"AsyncExecutor-"</span>);
    executor.initialize();
    <span style="font-weight: bold;">return</span> executor;
  }

}
</pre>
</div>
<p>
一般情况下只需要简单地在配置类上加 @EnableAsync 注解就完成配置了，而 Executor 不需要手动创建。
Spring默认使用SimpleAsyncTaskExecutor来异步运行这些方法。有两种方法覆写默认行为
</p>
</div>
<div class="outline-4" id="outline-container-org0eda4f4">
<h4 id="org0eda4f4">方法级别的设置</h4>
<div class="outline-text-4" id="text-org0eda4f4">
<div class="org-src-container">
<pre class="src src-java"><span style="font-weight: bold; text-decoration: underline;">@Configuration</span>
<span style="font-weight: bold; text-decoration: underline;">@EnableAsync</span>
<span style="font-weight: bold;">public</span> <span style="font-weight: bold;">class</span> <span style="font-weight: bold; text-decoration: underline;">SpringAsyncConfig</span> {
    <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">自己配置的Executor</span>
    <span style="font-weight: bold; text-decoration: underline;">@Bean</span>(name = <span style="font-style: italic;">"threadPoolTaskExecutor"</span>)
    <span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">Executor</span> <span style="font-weight: bold;">threadPoolTaskExecutor</span>() {
        <span style="font-weight: bold;">return</span> <span style="font-weight: bold;">new</span> <span style="font-weight: bold; text-decoration: underline;">ThreadPoolTaskExecutor</span>();
    }
}

<span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">在异步方法上使用指定的Executor</span>
<span style="font-weight: bold; text-decoration: underline;">@Async</span>(<span style="font-style: italic;">"threadPoolTaskExecutor"</span>)
<span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">void</span> <span style="font-weight: bold;">asyncMethodWithConfiguredExecutor</span>() {
    System.out.println(<span style="font-style: italic;">"Execute method with configured executor - "</span>
      + Thread.currentThread().getName());
}
</pre>
</div>
</div>
</div>
<div class="outline-4" id="outline-container-org74b5c87">
<h4 id="org74b5c87">应用级别的设置</h4>
<div class="outline-text-4" id="text-org74b5c87">
<p>
配置类实现AsyncConfigurer接口，实现的getAsyncExecutor方法返回的实例将成为程序内所有异步方法默认的Executor。
</p>
<div class="org-src-container">
<pre class="src src-java"><span style="font-weight: bold; text-decoration: underline;">@Configuration</span>
<span style="font-weight: bold; text-decoration: underline;">@EnableAsync</span>
<span style="font-weight: bold;">public</span> <span style="font-weight: bold;">class</span> <span style="font-weight: bold; text-decoration: underline;">SpringAsyncConfig</span> <span style="font-weight: bold;">implements</span> <span style="font-weight: bold; text-decoration: underline;">AsyncConfigurer</span> {

    <span style="font-weight: bold; text-decoration: underline;">@Override</span>
    <span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">Executor</span> <span style="font-weight: bold;">getAsyncExecutor</span>() {
        <span style="font-weight: bold;">return</span> <span style="font-weight: bold;">new</span> <span style="font-weight: bold; text-decoration: underline;">ThreadPoolTaskExecutor</span>();
    }

}
</pre>
</div>
</div>
</div>
</div>
<div class="outline-3" id="outline-container-org1b46606">
<h3 id="org1b46606">方法上的 @Async 注解</h3>
<div class="outline-text-3" id="text-org1b46606">
<p>
使用 @Async 注解需要注意：
</p>
<ul class="org-ul">
<li>必须是public方法，这样才能被Spring AOP代理</li>
<li>调用同一个类中带有@Async的方法并不会异步。同类的方法之间调用是直接调用原对象的方法，而不会通过代理调用，自然@Async注解也就不生效了</li>
</ul>
<p>
方法的返回值：
</p>
</div>
<div class="outline-4" id="outline-container-orga6b0a95">
<h4 id="orga6b0a95">void</h4>
<div class="outline-text-4" id="text-orga6b0a95">
<div class="org-src-container">
<pre class="src src-java"><span style="font-weight: bold; text-decoration: underline;">@Async</span>
<span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">void</span> <span style="font-weight: bold;">asyncMethodWithVoidReturnType</span>() {
    System.out.println(<span style="font-style: italic;">"Execute method asynchronously. "</span>
      + Thread.currentThread().getName());
}
</pre>
</div>
</div>
</div>
<div class="outline-4" id="outline-container-org1112362">
<h4 id="org1112362">有返回值的异步方法</h4>
<div class="outline-text-4" id="text-org1112362">
<p>
返回类型需要Future包装，Spring提供了Future的实现AsyncResult
</p>
<div class="org-src-container">
<pre class="src src-java"><span style="font-weight: bold; text-decoration: underline;">@Async</span>
<span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">Future</span>&lt;<span style="font-weight: bold; text-decoration: underline;">Long</span>&gt; <span style="font-weight: bold;">runTask</span>() {
    <span style="font-weight: bold; text-decoration: underline;">long</span> <span style="font-weight: bold; font-style: italic;">tm</span> = System.nanoTime();
    System.out.println(<span style="font-style: italic;">"-- Running task"</span>);
    <span style="font-weight: bold;">try</span> {
      Thread.sleep(5000);
    } <span style="font-weight: bold;">catch</span> (<span style="font-weight: bold; text-decoration: underline;">InterruptedException</span> <span style="font-weight: bold; font-style: italic;">e</span>) {
      e.printStackTrace();
    }
    System.out.println(<span style="font-style: italic;">"-- Task complete"</span>);
    <span style="font-weight: bold;">return</span> <span style="font-weight: bold;">new</span> <span style="font-weight: bold; text-decoration: underline;">AsyncResult</span>&lt;&gt;(System.nanoTime() - tm);
}
</pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="status" id="postamble">
<p class="date">Date: 2020-3-1</p>
<p class="author">Author: gdme1320</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
